﻿
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>根本停不下来</title>
</head>

<body>
    <div style="padding:5px; background:#BAAE9E;display:inline-block; border-radius:10px;">
        <canvas id="can"></canvas>
    </div>
</body>
<script>
    var padding_size = 10;
    var size = 120, r_size = size + padding_size, width = 0; height = 0, x_y = [], c = 0;
    var squ = [];
    var squColor = { "2": "#eee4da", "4": "#ece0c8", "8": "#f2b179", "16": "#f59563", "32": "#f57c5e", "64": "#f65d3b", "128": "#edcf72", "256": "#edcc61", "512": "#edcc61", "1024": "#edc53f", "2048": "#f30" };
    document.getElementById("can").setAttribute("width", (size + padding_size) * 4);
    document.getElementById("can").setAttribute("height", (size + padding_size) * 4);

    for (var i = 0; i < 4; i++) {
        for (var k = 0; k < 4; k++) {
            x_y[c] = { y: i * r_size + padding_size, x: k * r_size + padding_size };
            c++;
        }
    }

    var cans = document.getElementById("can").getContext('2d');
    width = cans.canvas.width;
    height = cans.canvas.height;
    var dra_back = function () {  // 画背景及网格
        cans.clearRect(0, 0, width, height);
        cans.canvas = null;
        cans.fillStyle = "#CDC1B4";
        cans.fillRect(0, 0, width, height); //背景
        for (var i = 0; i <= 4; i++) {

            cans.moveTo(i * r_size, 0);
            cans.lineTo(i * r_size, height);
            cans.lineWidth = padding_size * 2;
            cans.strokeStyle = '#BBADA0';
            cans.stroke();  // 竖

            cans.moveTo(0, i * r_size);
            cans.lineTo(width, i * r_size);
            cans.lineWidth = padding_size * 2;
            cans.strokeStyle = '#BBADA0';
            cans.stroke();  // 横
        }
    }

    var dra = function (o) { //画方块

        var txt = o.num;

        cans.fillStyle = squColor[txt]
        cans.fillRect(o.x_y.x, o.x_y.y, size - padding_size, size - padding_size);
        cans.beginPath();


        cans.font = '38px Helvetica';
        cans.fillStyle = "#fff";
        cans.fillStyle = 'orange';
        var met = cans.measureText(txt)
        var w = met.width;// 即为绘制后文字的宽度

        cans.textAlign = "center";
        cans.textBaseline = 'middle';//设置文本的垂直对齐方式
        cans.textAlign = 'center'; //设置文本的水平对对齐方式
        cans.fillText(txt, o.x_y.x + size / 2 - padding_size / 2, o.x_y.y + size / 2 - padding_size / 2);
    }



    var dra_rect = function () {  //生成方块
        if (squ.length >= c) { //
            //游戏结束
            alert('游戏结束');
            return;
        }
        var rom = x_y[parseInt(c * Math.random())];
        var o = { x_y: { x: rom.x, y: rom.y } };
        o.num = [2, 2, 2, 2, 2][parseInt(5 * Math.random())]; //生成数字
        // o.num = [2,4,8,16,32,64,128,256,512,1024,2048][parseInt(11 * Math.random())]; //生成数字

        for (var i = 0; i < squ.length; i++) {
            var e = squ[i];
            if (e.x_y.x == rom.x && e.x_y.y == rom.y) {
                // console.log(rom.x+"--"+rom.y)
                dra_rect();
                return;
            }
        }
        squ.push(o)
        dra(o);
    };
    var start = function () {
        dra_back();
        dra_rect();
        dra_rect();
    };
    start();

    document.getElementsByTagName("html")[0].addEventListener("keydown", function (e) {
        var keycode = e.keyCode
        if (keycode == 37 || keycode == 38 || keycode == 39 || keycode == 40) {
            oper.move(keycode);

        }
    }, false);

    window.oper = {
        row1: [],
        row2: [],
        row3: [],
        row4: [],
        t: null,
        interval: 200,  //动画时间
        ismove: false,
        move: function (keyCode) {
            this.t && this.animation_stop();

            var squ_length = squ.length;

            this.row1.length = 0;
            this.row2.length = 0;
            this.row3.length = 0;
            this.row4.length = 0;


            switch (keyCode) {
                case 37:
                    this.move_left();
                    break;
                case 38:
                    this.move_top();  // 上
                    break;
                case 39:
                    this.move_right();  //右
                    break;
                case 40:
                    this.move_bottom(); //下
                    break;
            }
            this.merge();

            if (squ_length != squ.length) {
                this.ismove = true;
            }


            this.animation();

        },
        over:function(){
            alert("游戏结束");
        },
        animation: function () {

            var star_date = new Date();
            interval = this.interval;
            this.t = setInterval(function () {
                dra_back();
                var cur_date = new Date()
                var is_over = false;

                for (var i = 0; i < squ.length; i++) {  //方块加动画
                    var e = squ[i];

                    if (e.x_y.x2 > e.x_y.x) {
                        e.x_y.x = e.x_y.x+(e.x_y.x2 - e.x_y.x) / this.interval * (cur_date.getTime() - star_date.getTime());
                    }
                    else if (e.x_y.x2 < e.x_y.x) {
                        e.x_y.x = e.x_y.x - (e.x_y.x - e.x_y.x2) / this.interval * (cur_date.getTime() - star_date.getTime());
                    }

                    if (e.x_y.y2 > e.x_y.y) {
                        e.x_y.y = e.x_y.y + (e.x_y.y2 - e.x_y.y) / this.interval * (cur_date.getTime() - star_date.getTime());
                    }
                    else if (e.x_y.y2 < e.x_y.y) {
                        e.x_y.y = e.x_y.y - (e.x_y.y - e.x_y.y2) / this.interval * (cur_date.getTime() - star_date.getTime());
                    }


                    if (this.interval + star_date.getTime() < cur_date.getTime()) {
                        if (e.x_y.x2) {
                            e.x_y.x = e.x_y.x2;
                        }
                        if (e.x_y.y2) {
                            e.x_y.y = e.x_y.y2;
                        }
                        is_over = true;
                    }

                    dra(e);
                }
                if (is_over) {
                    if (oper.ismove) {
                        dra_rect(); //有移动方块就 创建新的方块
                        oper.ismove = false;
                    }
                    clearInterval(oper.t);


                }
            }, 10)


        },
        animation_stop: function () {
            clearInterval(this.t);
            for (var i = 0; i < squ.length; i++) {  //方块加动画
                var e = squ[i];
                if (e.x_y.x2) {
                    e.x_y.x = e.x_y.x2;
                } if (e.x_y.y2) {
                    e.x_y.y = e.x_y.y2;
                }
                dra(e);
            }
            if (oper.ismove) {
                dra_rect(); //有移动方块就 创建新的方块
                oper.ismove = false;
            }

        },
        sort_x: function (isda) {
            var sort = function (row1, isda) {
                for (var i = 0; i < row1.length; i++) {
                    for (var j = i; j < row1.length; j++) {
                        if (row1[i].x_y.x > row1[j].x_y.x) {
                            var temp = row1[i];
                            row1[i] = row1[j];
                            row1[j] = temp;
                        }
                    }
                }
            }
            sort(this.row1);
            sort(this.row2);
            sort(this.row3);
            sort(this.row4);
        },
        sort_y: function (isda) {
            var sort = function (row1, isda) {
                for (var i = 0; i < row1.length; i++) {
                    for (var j = i; j < row1.length; j++) {
                        if (row1[i].x_y.y > row1[j].x_y.y) {
                            var temp = row1[i];
                            row1[i] = row1[j];
                            row1[j] = temp;
                        }
                    }
                }
            }
            sort(this.row1);
            sort(this.row2);
            sort(this.row3);
            sort(this.row4);
        },
        merge: function () {
            squ = [];  //数组 组合
            for (var i = 0; i < this.row1.length; i++) {
                if (!this.row1[i].isdel) {
                    squ[squ.length] = this.row1[i];
                }

            }
            for (var i = 0; i < this.row2.length; i++) {
                if (!this.row2[i].isdel) {
                    squ[squ.length] = this.row2[i];
                }
            }
            for (var i = 0; i < this.row3.length; i++) {
                if (!this.row3[i].isdel) {
                    squ[squ.length] = this.row3[i];
                }
            }
            for (var i = 0; i < this.row4.length; i++) {
                if (!this.row4[i].isdel) {
                    squ[squ.length] = this.row4[i];
                }
            }
            for (var i = 0; i < squ.length; i++) {  //循环 绘制方块
                var e = squ[i];
                if (e.x_y.x2&&e.x_y.x2 != e.x_y.x) {
                    this.ismove = true;
                }
                if (e.x_y.y2&&e.x_y.y2 != e.x_y.y) {
                    this.ismove = true;
                }
            }

        },
        move_left: function () {
            var reps = [0, 4, 8, 12];
            for (var i = 0; i < squ.length; i++) {
                var e = squ[i];
                if (e.x_y.y == x_y[reps[0]].y) {
                    this.row1[this.row1.length] = e;
                }
                if (e.x_y.y == x_y[reps[1]].y) {
                    this.row2[this.row2.length] = e;
                }
                if (e.x_y.y == x_y[reps[2]].y) {
                    this.row3[this.row3.length] = e;
                }
                if (e.x_y.y == x_y[reps[3]].y) {
                    this.row4[this.row4.length] = e;
                }
            }
            this.sort_x();

            var _left = function (row1) { //向左操作
                if (row1[0]) {
                    row1[0].x_y.x2 = 0 + padding_size;
                }
                if (row1[1]) {
                    if (row1[0].num == row1[1].num) {
                        row1[0].num = row1[0].num + row1[1].num;
                        row1[1].isdel = 1;
                    }
                    else {
                        row1[1].x_y.x2 = size * 1 + padding_size * 2;
                    }
                }
                if (row1[2]) {
                    if (!row1[1].isdel) {
                        if (row1[1].num == row1[2].num) {
                            row1[1].num = row1[1].num + row1[2].num;
                            row1[2].isdel = 1;
                        }
                        else {
                            row1[2].x_y.x2 = size * 2 + padding_size * 3;
                        }
                    } else {
                        row1[2].x_y.x2 = size * 1 + padding_size * 2;
                    }
                }
                if (row1[3]) {
                    if (!row1[2].isdel) {
                        if (row1[2].num == row1[3].num) {
                            row1[2].num = row1[2].num + row1[3].num;
                            row1[3].isdel = 1;
                        }
                        else if (row1[1].isdel) {
                            row1[3].x_y.x2 = size * 2 + padding_size * 3;
                        }
                        else {
                            row1[3].x_y.x2 = size * 3 + padding_size * 4;
                        }
                    }
                    else {
                        row1[3].x_y.x2 = size * 2 + padding_size * 3;
                    }
                }
            }
            _left(this.row1);
            _left(this.row2);
            _left(this.row3);
            _left(this.row4);

        },
        move_right: function () {
            var reps = [0, 4, 8, 12];
            for (var i = 0; i < squ.length; i++) {
                var e = squ[i];
                if (e.x_y.y == x_y[reps[0]].y) {
                    this.row1[this.row1.length] = e;
                }
                if (e.x_y.y == x_y[reps[1]].y) {
                    this.row2[this.row2.length] = e;
                }
                if (e.x_y.y == x_y[reps[2]].y) {
                    this.row3[this.row3.length] = e;
                }
                if (e.x_y.y == x_y[reps[3]].y) {
                    this.row4[this.row4.length] = e;
                }
            }
            this.sort_x();

            var _right = function (row1) { //向右操作
                if (row1[row1.length - 1]) {
                    row1[row1.length - 1].x_y.x2 = size * 3 + padding_size * 4;
                }

                if (row1[row1.length - 2]) {
                    if (row1[row1.length - 1].num == row1[row1.length - 2].num) {
                        row1[row1.length - 1].num *= 2;
                        row1[row1.length - 2].isdel = 1;
                    }
                    else {
                        row1[row1.length - 2].x_y.x2 = size * 2 + padding_size * 3;
                    }

                }
                if (row1[row1.length - 3]) {
                    if (!row1[row1.length - 2].isdel) {
                        if (row1[row1.length - 2].num == row1[row1.length - 3].num) {
                            row1[row1.length - 2].num *= 2;
                            row1[row1.length - 3].isdel = 1;
                        }
                        else {
                            row1[row1.length - 3].x_y.x2 = size * 1 + padding_size * 2;
                        }
                    } else {
                        row1[row1.length - 3].x_y.x2 = size * 2 + padding_size * 3;
                    }

                }
                if (row1[row1.length - 4]) {
                    if (!row1[row1.length - 3].isdel) {
                        if (row1[1].num == row1[0].num) {
                            row1[1].num *= 2;
                            row1[0].isdel = 1;
                        }
                        else if (row1[row1.length - 2].isdel) {
                            row1[0].x_y.x2 = size * 1 + padding_size * 2;
                        }
                        else {
                            row1[0].x_y.x2 = 0 + padding_size;
                        }
                    } else {
                        row1[0].x_y.x2 = size * 1 + padding_size * 2;
                    }
                }
            }

            _right(this.row1);
            _right(this.row2);
            _right(this.row3);
            _right(this.row4);

        },
        move_top: function () {
            var reps = [0, 1, 2, 3];
            for (var i = 0; i < squ.length; i++) {
                var e = squ[i];
                if (e.x_y.x == x_y[reps[0]].x) {
                    this.row1[this.row1.length] = e;
                }
                if (e.x_y.x == x_y[reps[1]].x) {
                    this.row2[this.row2.length] = e;
                }
                if (e.x_y.x == x_y[reps[2]].x) {
                    this.row3[this.row3.length] = e;
                }
                if (e.x_y.x == x_y[reps[3]].x) {
                    this.row4[this.row4.length] = e;
                }
            }
            this.sort_y();

            var _top = function (row1) {
                if (row1[0]) {
                    row1[0].x_y.y2 = 0 + padding_size;
                }
                if (row1[1]) {
                    if (row1[0].num == row1[1].num) {
                        row1[0].num = row1[0].num + row1[1].num;
                        row1[1].isdel = 1;
                    }
                    else {
                        row1[1].x_y.y2 = size * 1 + padding_size * 2;
                    }
                }
                if (row1[2]) {
                    if (!row1[1].isdel) {
                        if (row1[1].num == row1[2].num) {
                            row1[1].num = row1[1].num + row1[2].num;
                            row1[2].isdel = 1;
                        }
                        else {
                            row1[2].x_y.y2 = size * 2 + padding_size * 3;
                        }
                    } else {
                        row1[2].x_y.y2 = size * 1 + padding_size * 2;
                    }
                }
                if (row1[3]) {
                    if (!row1[2].isdel) {
                        if (row1[2].num == row1[3].num) {
                            row1[2].num = row1[2].num + row1[3].num;
                            row1[3].isdel = 1;
                        }
                        else if (row1[1].isdel) {
                            row1[3].x_y.y2 = size * 2 + padding_size * 3;
                        }
                        else {
                            row1[3].x_y.y2 = size * 3 + padding_size * 4;
                        }
                    }
                    else {
                        row1[3].x_y.y2 = size * 2 + padding_size * 3;
                    }
                }
            }
            _top(this.row1);
            _top(this.row2);
            _top(this.row3);
            _top(this.row4);

        },
        move_bottom: function () {
            var reps = [0, 1, 2, 3];
            for (var i = 0; i < squ.length; i++) {
                var e = squ[i];
                if (e.x_y.x == x_y[reps[0]].x) {
                    this.row1[this.row1.length] = e;
                }
                if (e.x_y.x == x_y[reps[1]].x) {
                    this.row2[this.row2.length] = e;
                }
                if (e.x_y.x == x_y[reps[2]].x) {
                    this.row3[this.row3.length] = e;
                }
                if (e.x_y.x == x_y[reps[3]].x) {
                    this.row4[this.row4.length] = e;
                }
            }
            this.sort_y();

            var _bottom = function (row1) {
                if (row1[row1.length - 1]) {
                    row1[row1.length - 1].x_y.y2 = size * 3 + padding_size * 4;
                }

                if (row1[row1.length - 2]) {
                    if (row1[row1.length - 1].num == row1[row1.length - 2].num) {
                        row1[row1.length - 1].num *= 2;
                        row1[row1.length - 2].isdel = 1;
                    }
                    else {
                        row1[row1.length - 2].x_y.y2 = size * 2 + padding_size * 3;
                    }

                }
                if (row1[row1.length - 3]) {
                    if (!row1[row1.length - 2].isdel) {
                        if (row1[row1.length - 2].num == row1[row1.length - 3].num) {
                            row1[row1.length - 2].num *= 2;
                            row1[row1.length - 3].isdel = 1;
                        }
                        else {
                            row1[row1.length - 3].x_y.y2 = size * 1 + padding_size * 2;
                        }
                    } else {
                        row1[row1.length - 3].x_y.y2 = size * 2 + padding_size * 3;
                    }

                }
                if (row1[row1.length - 4]) {
                    if (!row1[row1.length - 3].isdel) {
                        if (row1[1].num == row1[0].num) {
                            row1[1].num *= 2;
                            row1[0].isdel = 1;
                        }
                        else if (row1[row1.length - 2].isdel) {
                            row1[0].x_y.y2 = size * 1 + padding_size * 2;
                        }
                        else {
                            row1[0].x_y.y2 = 0 + padding_size;
                        }
                    } else {
                        row1[0].x_y.y2 = size * 1 + padding_size * 2;
                    }
                }
            }
            _bottom(this.row1);
            _bottom(this.row2);
            _bottom(this.row3);
            _bottom(this.row4);

        }
    };

</script>
</html>
